package be.rivendale.renderer.mk2.remote;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;

public class SocketStreamer {
    private Socket socket;
    private ObjectInputStream inputStream;
    private ObjectOutputStream outputStream;

    public SocketStreamer(Socket socket) {
        this.socket = socket;
        this.outputStream = openOutputStream(socket);
        this.inputStream = openInputStream(socket);
    }

    private static ObjectOutputStream openOutputStream(Socket socket) {
        try {
             return new ObjectOutputStream(socket.getOutputStream());
        } catch (IOException exception) {
            throw new RuntimeException("Unable to open output stream for socket", exception);
        }
    }

    private static ObjectInputStream openInputStream(Socket socket) {
        try {
            return new ObjectInputStream(socket.getInputStream());
        } catch (IOException exception) {
            throw new RuntimeException("Unable to create input stream for socket", exception);
        }
    }

    public <READ_TYPE> READ_TYPE read() {
        try {
            return (READ_TYPE)inputStream.readObject();
        } catch (IOException exception) {
            throw createReadFailedException(exception);
        } catch (ClassNotFoundException exception) {
            throw createReadFailedException(exception);
        }
    }

    private RuntimeException createReadFailedException(Exception exception) {
        return new RuntimeException("Unable to read object from socket stream", exception);
    }

    public <WRITE_TYPE> void write(WRITE_TYPE object) {
        try {
            outputStream.writeObject(object);
        } catch (IOException exception) {
            throw new RuntimeException("Unable to write object to socket stream", exception);
        }
    }
}
